# Create your views here.
from django.contrib.auth.models import User
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.contrib.auth import logout
from django.template import RequestContext
from django.db import transaction
from market.authentification import authentificatePlayer, authentificateUser
from market.marketData import MarketData
from market.models import BetRoom, Strategy, AssetPercentageInStrategy, Fund, DigitalContract, LastVisitedContract, TradedContract
from market.models import Asset, Player, History, PlayerPortfolioForHistory
from market.strategyAndFundHelper import getFundMtM, getPortfolioMtM, getBankAccount
from market.sendEmailToPlayers import sendEmailToPlayersOfTheBetroom
from market.chat.betroomBot import sendOnBetroomChat

from market.killAssetHelper import killAssetWithConstantMtM
from market.killAssetHelper import killAssetWithConstantNumbers

from market.stupidUserException import StupidUserException
from market.exceptionHandler import handleRequestPlayerPOSTWithExceptionWhenNotSuspended
from market.exceptionHandler import handleRequestBetroomPOSTWithException, handleRequestBetroomAdminPOSTWithException
from market.lastVisitedContractHelper import getLastVisitedContract

from datetime import datetime
import os, os.path
from market.baseCreator import constructRoomFromFiles
from market.baseSaver import saveRoomToFiles


################################################################################################################
#site admin to launch some code from the web site
# this was originaly a command excecuted via manage.py, but this is not possible
# to run manage.py on the production server.
# This part call the code which save the base
def saveRoomFromWeb0(request, betroom):
        saveRoomToFiles( os.path.join(os.getcwd(), 'savedRoomFiles'), betroom )
	return 0
def saveRoomFromWeb(request):
        return handleRequestBetroomPOSTWithException( globals()["saveRoomFromWeb0"], request )



################################################################################################################
#site admin to launch some code from the web site
# this was originaly a command excecuted via manage.py, but this is not possible
# to run manage.py on the production server.
# This part call the code which create the base from the files.
# the files are tested before modifying the data base.
def createRoomFromWeb0(request, betroom):
        path = ''
        try:
                path = request.POST['path']
        except:
                path = ''
        constructRoomFromFiles( path, betroom )
        return 0

def createRoomFromWeb(request):
         return handleRequestBetroomAdminPOSTWithException( globals()["createRoomFromWeb0"], request )


################################################################################################################
# change the description of the betroom
def changeDescription0(request, betroom):
        desc = ''
        nextLoc = '/adminHome/'
        try:
                desc = request.POST['description_text']
        except:
                desc = ''
        try:
                nextLoc = request.POST['nextLoc']
        except:
               pass
        betroom.description = desc
        betroom.save()
        return HttpResponseRedirect(nextLoc)

# change the description of the betroom
def changeDescription(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["changeDescription0"], request )


################################################################################################################
# creates a new player with Mkt view (so that the other player MtM will not change
# the Player will be fully invested in his main strategy and the number of action associated to it
# will be such that the MtM of the player will be the average og the other player's MtMs
def createPlayerWithMktViewAndAverageMtM0(request, betroom):

        # get and check the new player name
        newPlayerName = request.POST["newPlayerName"]
        if newPlayerName == "":
                raise StupidUserException( 'The new player name cannot be the empty string.' )
        if " " in newPlayerName:
                raise StupidUserException( 'The new player name cannot contain space.' )

        userList = User.objects.filter(username = newPlayerName)
        if len(userList) != 1:
                return HttpResponse( 'There is no user with this name. You can only add a player if he is a Celibax user.' )
        
        playersWithThisName = Player.objects.filter( userBeingThisPlayer__username = newPlayerName, mainStrategy__betroom = betroom )
        if len(playersWithThisName) > 0:
                return HttpResponse(  newPlayerName+ ' is already a player in this betroom.' )

        usersWithThisNameList = User.objects.filter( username = newPlayerName )
        if len(usersWithThisNameList)==1:
            user = usersWithThisNameList[0]
        else:
            user = User(username = newPlayerName )
            user.save()
        
        

        # compute the average MtM
        allOldPlayers = Player.objects.filter( mainStrategy__betroom = betroom )
        nOldPlayers = len( allOldPlayers )
        m = MarketData(betroom)
        if nOldPlayers == 0:
                raise Exception( 'There is currently no player. You cannot add a new player in this condition' )
        averageMtM = 0
        for p in allOldPlayers:
                averageMtM += getPortfolioMtM( p, m )
        averageMtM = averageMtM / nOldPlayers
        

        if betroom.roomType == 0:
                #create the the strategy, player and the number of asset in the strategy
                newPlayerStrategyName = newPlayerName + "Strat" + betroom.name
                newPlayerStrategy = Strategy( name = newPlayerStrategyName, betroom = betroom )
                newPlayerStrategy.save()
                newPlayer = Player( userBeingThisPlayer = user, mainStrategy = newPlayerStrategy )
                newPlayer.save()
                mktMtM = m.getMktStratMtM()
                if mktMtM == 0:
                        raise Exception( 'Market MtM should not be 0' )
                totalNumberOfAction = averageMtM / mktMtM
                newFund = Fund(
                        strategy = newPlayerStrategy,
                        player = newPlayer,
                        fundTargetPercentageInPortfolio = 1,
                        numberOfAssetsInFund = totalNumberOfAction )
                newFund.save()
                #fill the strategy
                mktView = m.getMarketView()
                for asset in mktView.viewOnAssets:
                        newAssetPercentageInStrategy = AssetPercentageInStrategy(
                                asset = asset[0],
                                strategy = newPlayerStrategy,
                                assetPercentageInStrategy = asset[1] )
                        newAssetPercentageInStrategy.save()
        else:
                newPlayer = Player( userBeingThisPlayer = user, mainStrategy = getBankAccount(betroom) )
                newPlayer.save()
                fund = Fund(
                        player = newPlayer,
                        strategy = getBankAccount(betroom),
                        fundTargetPercentageInPortfolio = 1,
                        numberOfAssetsInFund = averageMtM
                        )
                fund.save()
                

        #end
        return 0

def createPlayerWithMktViewAndAverageMtM(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["createPlayerWithMktViewAndAverageMtM0"], request )

                
################################################################################################################
def getAssetToKill(request, betroom):
        # get and check the asset name
        try:
                assetToKillName = request.POST["assetToKillName"]
        except:
                raise StupidUserException("The string in assetToKillName has not been found in the POST request")
        try:
                return Asset.objects.get( name = assetToKillName, betroom = betroom )
        except:
                raise StupidUserException("There is no asset called %s" %assetToKillName)
                

################################################################################################################
# idendtifcation and call to killAssetWithConstantNumbers
def killAssetNumbers0(request, betroom):
        killAssetWithConstantNumbers( getAssetToKill(request, betroom) )
        return 0

def killAssetNumbers(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["killAssetNumbers0"], request )



################################################################################################################
# idendtifcation and call to killAsset at constant MtM
def killAssetMtM0(request, betroom):
        perentageOfTheMtMInvestedInThisAssetToPayAsADividend = 0
        killAssetWithConstantMtM( getAssetToKill(request, betroom), perentageOfTheMtMInvestedInThisAssetToPayAsADividend )
        return 0

def killAssetMtM(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["killAssetMtM0"], request )


################################################################################################################
# suspend the transactions of the betroom
def suspendTransaction0(request, betroom):
        betroom.status = 2;
        betroom.save()
	return 0

################################################################################################################
def suspendTransaction(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["suspendTransaction0"], request )


################################################################################################################
# resume the transactions of the betroom
def resumeTransaction0(request, betroom):
        betroom.status = 1
        betroom.save()
        return 0
        
################################################################################################################
def resumeTransaction(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["resumeTransaction0"], request )

################################################################################################################
# send an email to the player of the betroom
def sendEmail0(request, betroom):
        sendEmailToPlayersOfTheBetroom( betroom, request.POST['email_object'], request.POST['email_text'] )
        return 0

def sendEmail(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["sendEmail0"], request )



################################################################################################################
# fix or unfix the contract
def fixOrUnfixContract0(request, betroom):
        newStatus = -2
        if request.POST["fixingGroup"] == "fix":
                newStatus = -1
        # in the by contract room, the admin is also a player...
        player = Player.objects.get( userBeingThisPlayer = request.user, mainStrategy__betroom = betroom )
        contract = getLastVisitedContract( player )
        # if the new status is also the old status, return
        if newStatus == contract.settlementStatus:
                return 0
        if contract.settlementStatus > -1:
                raise StupidUserException("The contract is already setlled and its status cannot change.")
        if newStatus == -2 and contract.expiry < datetime.now():
                raise StupidUserException("The contract should remain fixed once it has expired.")
        contract.settlementStatus = newStatus
        contract.save()
        if newStatus == -2:
                msg = 'The transactions on '+ contract.name+  ' are resumed.'
        if newStatus == -1:
                msg = contract.name+ ' has been fixed and is now waiting for settlement. Alternatively the transactions could be resumed in case of an unjustified fixing'
        if newStatus > -1:
                msg = contract.name+ ' has been settled. '
                if newStatus == 0:
                        msg = msg +'Contract holders received nothing'
                if newStatus == 1:
                        msg = msg +'Contract holders received 100 chochoros per contract'
                if newStatus == 2:
                        msg = msg +'Unfortunatly, it was not possible to determine either it should pay or not. Buyers have been refunded.'
        sendOnBetroomChat( betroom, request.user.username, str(msg) ) 
        return 0

def fixOrUnfixContract(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["fixOrUnfixContract0"], request )



################################################################################################################
# fix or unfix the contract
def settleContract0(request, betroom):
        newStatus = -1
        if request.POST["settleGroup"] == "doNotPay":
                newStatus = 0
        if request.POST["settleGroup"] == "pay":
                newStatus = 1
        if request.POST["settleGroup"] == "refund":
                newStatus = 2
        if newStatus == -1:
                raise StupidUserException("Unrecognised settlement type")
        # in the by contract room, the admin is also a player...
        player = Player.objects.get( userBeingThisPlayer = request.user, mainStrategy__betroom = betroom )
        contract = getLastVisitedContract( player )
        if contract.settlementStatus > -1:
                raise StupidUserException("The contract is already setlled and its status cannot change.")
        if contract.settlementStatus != -1:
                raise StupidUserException("For security reasons, it is requiered to fix the contract before settling it.")

        # if the contract holder do not receive any payment, just return
        if newStatus == 0:
                contract.settlementStatus = 0
                contract.save()
                return 0

        # if the contract holder do not receive the cash, proceed to the payments
        # if the settlement tyoe is 2, refund the buyer at te traded price
        if newStatus != 1 and newStatus != 2:
                raise Exception("Unexpected situassion settlin contract.")

        tradedContractList = TradedContract.objects.filter( contract = contract )
        for tc in tradedContractList:
                transferedAmount = 100
                if newStatus ==  2:
                        transferedAmount = tc.tradedPrice
                buyingFund = Fund.objects.get( player = tc.buyer )
                buyingFund.numberOfAssetsInFund = buyingFund.numberOfAssetsInFund + transferedAmount
                buyingFund.save()
                sellingFund = Fund.objects.get( player = tc.seller )
                sellingFund.numberOfAssetsInFund = sellingFund.numberOfAssetsInFund - transferedAmount
                sellingFund.save()
        
        contract.settlementStatus = newStatus
        contract.save()

        # create an history
        actionTakenStr = contract.name +' settled with type ' + str(newStatus) +'.'
        h = History( bettingPlayerName = player, betroom = betroom, actionTaken = actionTakenStr )
        h.save()
        for p in Player.objects.filter( mainStrategy__betroom = betroom):
                mtm = Fund.objects.get( player = p ).numberOfAssetsInFund
                pfh = PlayerPortfolioForHistory( player=p, history=h, portfolioMtM=mtm, investementInMainStrategyPercentage=1, numberOfStrategies=1)
                pfh.save()


        return 0

def settleContract(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["settleContract0"], request )


                

